from collections import Iterable
from utils.base_response import BaseResponse
import json


class AssertTool:
    def __init__(self, assert_data, response_data, show_status=False):
        self.assert_data = assert_data  # 断言数据
        self.response_data = response_data  # 响应数据
        self.show_status = show_status  # 是否显示所有数据
        self.assert_status = True  # 断言结果
        self.result_data = {} if isinstance(assert_data, dict) else []  # 对比结果
        self.res = BaseResponse()

    def add_data(self, assert_data, assert_value, response_value, result_data, pk_str, key):
        assert_status = False
        show_str = '相同'
        if assert_value != response_value:
            assert_status = True
            show_str = '不相同'
            self.assert_status = False  # 断言不通过
        if self.show_status or assert_status:
            if isinstance(result_data, list):
                pk = assert_data.get(pk_str)
                if result_data:
                    item_data = result_data[-1]
                    if isinstance(item_data, dict):
                        if item_data.get(pk_str) == pk:
                            item_data[key] = [show_str, assert_value, response_value]
                        else:
                            if pk_str == key:
                                result_data.append({pk_str: pk})
                            else:
                                result_data.append({pk_str: pk, key: [show_str, assert_value, response_value]})
                    else:
                        self.res.status = 1
                        self.res.msg = '数据有误，无法校验(ApiAssertTool)'
                else:
                    if pk_str == key:
                        result_data.append({pk_str: pk})
                    else:
                        result_data.append({pk_str: pk, key: [show_str, assert_value, response_value]})
            else:
                result_data[key] = [show_str, assert_value, response_value]

    def assert_func(self, assert_data, response_data, result_data):
        pk_str = 'id'
        if type(assert_data) == type(response_data):
            for key in assert_data:
                if isinstance(assert_data, list):
                    assert_types = {type(ast) for ast in assert_data}
                    response_types = {type(ast) for ast in response_data}
                    if len(assert_types) != 1 or len(response_types) != 1 or (assert_types != response_types):
                        self.assert_status = False  # 断言不通过
                        result_data.append(['数组数据类型不一致', assert_data, response_data])
                        return
                    if isinstance(key, str) or isinstance(key, int):
                        if key not in response_data:
                            self.assert_status = False  # 断言不通过
                            result_data.append(['找不到元素', key, None])
                        elif self.show_status:
                            result_data.append([key, key])
                    else:
                        if isinstance(key, dict):
                            pk = key.get(pk_str)
                            if not pk:
                                self.assert_status = False  # 断言不通过
                                result_data.append(['断言数据中不存在id字段！', key, None])
                                return
                            res_data = [item for item in response_data if item.get(pk_str) == pk]
                            if not res_data:
                                self.assert_status = False  # 断言不通过
                                result_data.append(['响应数据不存在该数据！', pk, None])
                                return
                            if len(res_data) == 1:
                                self.assert_func(key, res_data[0], result_data)
                            else:
                                self.assert_status = False  # 断言不通过
                                result_data.append(['响应数据中存在重复数据！', pk, res_data])
                                return
                        else:
                            if key not in response_data:
                                self.assert_status = False  # 断言不通过
                                result_data.append(['数据不存在于响应数据中！', key, response_data])
                                return
                            elif self.show_status:
                                result_data.append(['元素相同！', key, key])
                elif isinstance(assert_data, dict):
                    assert_value = assert_data.get(key)  # 得到断言value
                    response_value = response_data.get(key)  # 得到响应value
                    if isinstance(assert_value, str) or isinstance(assert_value, int):
                        self.add_data(assert_data, assert_value, response_value, result_data, pk_str, key)
                    elif isinstance(assert_value, Iterable):  # 判断是否为可迭代对象
                        if isinstance(response_value, Iterable):
                            if isinstance(result_data, dict):
                                result_data[key] = [] if isinstance(assert_value, list) else {}
                                self.assert_func(assert_value, response_value, result_data[key])
                            else:
                                result_data[-1][key] = [] if isinstance(assert_value, list) else {}
                                self.assert_func(assert_value, response_value, result_data[-1][key])
                        else:
                            self.add_data(assert_data, assert_value, response_value, result_data, pk_str, key)
        else:
            self.assert_status = False  # 断言不通过
            if isinstance(result_data,list):
                result_data.append(['数据类型不一致',assert_data, response_data])
            else:
                result_data['type'] = ['数据类型不一致',assert_data, response_data]

    def run(self):
        self.assert_func(self.assert_data, self.response_data, self.result_data)

    def dict(self):
        if not self.assert_status:
            self.res.status = 1
            self.res.msg = '断言失败'
        return {
            'result_data': self.result_data,
            'show_status': self.show_status,
            'assert_status': self.assert_status,
        }


if __name__ == '__main__':
    a = {'count': 2, 'lis': [1, 2, 3,], 'results': [
        {'env_protocol': 'http', 'env_ip': '127.0.0.1', 'env_port': '81111', 'env_title': '自动化测试平台',
         'token': 'fgsadfgafdg',
         'status': 1},
        {'env_protocol': 'http', 'env_ip': '127.0.0.1', 'env_port': '81112', 'env_title': '佣金测试环境', 'token': '',
         'status': 1}]}

    b = {'count': 2, 'a': 1, 'next': None, 'previous': None, 'results': [
        {'id': 1, 'c': 1, 'create_time': None, 'update_time': None, 'env_protocol': 'http', 'env_ip': '127.0.0.1',
         'env_port': '81111', 'env_domain': None, 'env_title': '自动化测试平台', 'token': '', 'status': 1},
        {'id': 1, 'c': 1, 'create_time': None, 'update_time': None, 'env_protocol': 'http', 'env_ip': '127.0.0.1',
         'env_port': '81111', 'env_domain': None, 'env_title': '自动化测试平台', 'token': '', 'status': 1},
        {'id': 2, 'create_time': None, 'update_time': None, 'env_protocol': 'http', 'env_ip': '127.0.0.1',
         'env_port': '81112', 'env_domain': None, 'env_title': '佣金测试环境', 'token': '', 'status': 1,
         'bn': [
             {'id': 1, 'a': 1, 'b': 2},
             {'id': 2, 'a': 2, 'b': 3, 'c': [1, 2, 3, ], 'sdf': {
                 'a': 12,
                 'b': 13,
                 'c': 15,
             }}
         ],
         'bbb': [[1, 2], [3, 4]],
         'ccc': [{'python': 'python1'}, {'java': 'java1'}]
         }]}

    c = {'count': 2, 'a': 'a', 'results': [
        {'id': 1, 'c': 'c', 'env_protocol': 'http', 'env_ip': '127.0.0.21', 'env_port': '81111', 'env_title': '自动化测试平台',
         'token': '',
         'status': 1},
        {'id': 2, 'env_protocol': 'http', 'env_ip': '127.0.0.1', 'env_port': '81112', 'env_title': '佣金测试环境',
         'token': '',
         'status': 1,
         'bn': [
             {'id': 1, 'a': 2, 'b': 2},
             {'id': 2, 'a': 2, 'b': 3, 'c': [1, 2, 3, 4], 'sdf': {
                 'a': 12,
                 'b': 13,
                 'c': 14,
             }}
         ],
         'bbb': [[1, 2], [3, 5]],
         'ccc': [{'python': 'python1'}, {'java': 'java1'}]
         }
        # , 22
    ]}

    d = {'count': 2, 'lis': [1, 2, 3, 4]}
    sd = {}

    # tb = ApiAssertTool(a, a)
    # tb = ApiAssertTool(b, b)
    # tb = ApiAssertTool(c, c)
    # tb = ApiAssertTool(d, d)
    # tb = ApiAssertTool(a, b)
    # tb = ApiAssertTool(a, c)
    # tb = ApiAssertTool(a, d)
    # tb = ApiAssertTool(b, a)
    # tb = ApiAssertTool(b, c)
    # tb = ApiAssertTool(b, d)
    # tb = ApiAssertTool(c, b, True)
    # tb = ApiAssertTool(c, b)
    tb.run()
    data = tb.dict()
    print(json.dumps(data))
    # print(data)
    aaa = {
        "status_code": 0,  # 0：相等 1：不相等 2：数据重复
        "msg": "",  # 提示
        "assert_data": None,  # 断言数据
        "response_data": None  # 响应数据
    }
